
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <amanita/aMath.h>
#include <amanita/aString.h>
#include "../Page.h"
#include "TarotStar.h"
#include "CardSet.h"
#include "Card.h"


const char TarotStar::EDW[16] = {
	 0,	// None
	 8,	// Earth
	 8,	// Air
	-4,	// Air - Earth
	 8,	// Water
	 4,	// Water - Earth
	 2,	// Water - Air
	 2,	// Water - Air - Earth
	 8,	// Fire
	 2,	// Fire - Earth
	 4,	// Fire - Air
	 2,	// Fire - Air - Earth
	-4,	// Fire - Water
	 2,	// Fire - Water - Earth
	 2,	// Fire - Water - Air
	 4		// Fire - Water - Air - Earth
};


TarotStar::TarotStar(TarotDeck &d) : CardSet() {
	setDeck(d);
	star = 0;
	picked = 0;
}

TarotStar::~TarotStar() {
	if(star) {
		for(int i=0; i<sz; i++) {
			if(star[i].name) free(star[i].name);
			if(star[i].title) free(star[i].title);
		}
		free(star);
		star = 0;
	}
}

void TarotStar::paint(cairo_t *cr,GdkRectangle *rects,int nrects) {
	if(!star || !sz || !isVisible()) return;
	for(int i=0,n; i<sz; i++) {
		if(rects && nrects) {
			for(n=0; !intersects(i,rects[n]) && n<nrects; n++);
			if(n==nrects) continue;
		}
		star_card &sc = star[i];
		Page::setColor(cr,0xffffff);
		cairo_rectangle(cr,sc.x,sc.y,sc.width,sc.height);
		cairo_stroke_preserve(cr);
		Page::setColor(cr,0x000066);
		cairo_fill(cr);
	}
	CardSet::paint(cr,rects,nrects);
}

int TarotStar::getStarWidth() {
	return aMath::round(((double)deck->getWidth()/(double)grid.card_width)*(double)grid.width);
}

int TarotStar::getStarHeight() {
	return aMath::round(((double)deck->getHeight()/(double)grid.card_height)*(double)grid.height);
}


void TarotStar::placeCards(GdkRectangle &r) {
	if(!star) return;
	int i,n,sx = r.x+(r.width-getStarWidth())/2,sy = r.y+(r.height-getStarHeight())/2;
	double g = (double)deck->getWidth()/(double)grid.card_width;
	Card *c;
	width = deck->getWidth(),height = deck->getHeight();
	for(i=0; i<sz; i++) {
		star_card &sc = star[i];
		sc.x = sx+aMath::round((double)sc.grid_x*g);
		sc.y = sy+aMath::round((double)sc.grid_y*g);
		sc.width = width;
		sc.height = height;
		if(sc.state&CARD_FLIPPED) n = sc.width,sc.width = sc.height,sc.height = n;
app.printf("TarotStar::placeCards(%d,grid_x=%d,grid_y=%d,x=%d,y=%d,w=%d,h=%d)",i,sc.grid_x,sc.grid_y,sc.x,sc.y,sc.width,sc.height);
		c = cards[i];
		if(c) c->setLocation(sc.x+(sc.width-c->getWidth())/2,sc.y+(sc.height-c->getHeight())/2);
	}
}

void TarotStar::getBounds(int i,GdkRectangle &r) {
	if(!star || i<0 || i>=(int)sz) r.x = 0,r.y = 0,r.width = 0,r.height = 0;
	else {
		star_card &sc = star[i];
		r.x = sc.x-5,r.y = sc.y-5,r.width = sc.width+10,r.height = sc.height+10;
	}
}

int TarotStar::findCardIndex(int x,int y) {
	for(int i=sz; i>=0; i--) {
		star_card &sc = star[i];
		if(x>=sc.x && y>=sc.y && x<sc.x+sc.width && y<sc.y+sc.height) return i;
	}
	return -1;
}

bool TarotStar::contains(int i,int x,int y) {
	if(!star || i<0 || i>=(int)sz) return false;
	star_card &sc = star[i];
	return x>=sc.x && y>=sc.y && x<sc.x+sc.width && y<sc.y+sc.height;
}

bool TarotStar::intersects(int i,GdkRectangle &r) {
	if(!star || i<0 || i>=(int)sz) return false;
	star_card &sc = star[i];
	return r.x<sc.x+sc.width && r.y<sc.y+sc.height && r.x+r.width>=sc.x && r.y+r.height>=sc.y;
}

void TarotStar::pickCard(Card &c,int i) {
app.printf("TarotStar::pickCard(sz=%d,picked=%d,card=%s)",sz,picked,c.getName());
	if(picked==sz) return;
	if(i<0 || i>=sz) i = picked;
	CardSet &cs = c.getCardSet();
	star_card &sc = star[i];
	cs.remove(c);
	c.setCardSet(*this);
	c.setState(sc.state|(c.isReversed()? CARD_REVERSED : 0));
	c.setLocation(sc.x+(sc.width-c.getWidth())/2,sc.y+(sc.height-c.getHeight())/2);
	if(cards[i]) {
		cards[i]->returnToOriginalState();
		cards[i]->getCardSet().add(*cards[i]);
	} else picked++;
	cards[i] = &c;
}


FILE *TarotStar::openFile(const char *fn) {
	return app.fopenlangf(0,"tarot/star.%s.txt",fn);
}

void TarotStar::readHeader(FILE *fp) {
	int n,l[16];
	aString str;
	CardSet::readHeader(fp);
	str.appendTab(fp);
	n = str.toIntArray(l);
	grid.card_width = l[0];
	grid.card_height = l[1];
	grid.width = l[2];
	grid.height = l[3];
	(void)n;
}

void TarotStar::readCards(FILE *fp) {
	size_t n;
	int i,l[16];
	aString str;
	star = (star_card *)malloc(sz*sizeof(star_card));
	for(i=0; i<sz; i++) {
		star_card &sc = star[i];
		str.clear().appendTab(fp);
		n = str.toIntArray(l);
		str.clear().appendTab(fp);
		sc.name = strdup(str.toCharArray());
		str.clear().appendTab(fp);
		sc.title = strdup(str.toCharArray());
		sc.x = 0;
		sc.y = 0;
		sc.width = 0;
		sc.height = 0;
		sc.grid_x = l[0];
		sc.grid_y = l[1];
		sc.state = CARD_PICKED|l[2];
		sc.edw = 0;
		cards[i] = 0;
	}
	(void)n;
}


void TarotStar::analyze() {
	int i,n;
	edmin = 0x7fff,edmax = 0,edsum = 0;
	memset(elements,0,sizeof(elements));
	memset(types,0,sizeof(types));
	memset(groups,0,sizeof(groups));
	Card *c;
	for(i=0; i<sz; i++) if((c=cards[i])) {
app.printf("TarotStar::analyze(number=%d)",c->getNumber());
		for(n=0; n<sz; n++) if(i!=n) star[i].edw += edWeight((int)c->getElement(),(int)cards[n]->getElement());
		n = star[i].edw;
		if((int)n<edmin) edmin = n;
		if((int)n>edmax) edmax = n;
		edsum += n;
		for(n=0; n<4; n++) elements[n] += c->ed(n);
		types[c->isMajor()? 0 : (c->isCourt()? 1 : 2)]++;
		if(c->isMinor()) groups[c->getNumber()-1]++;
	}
}

